<template>
  <section
    v-loading="loading"
    class="dialog-body"
  >
    <el-row>
      <el-col :span="14">
        <section
          id="storePlanImageId"
          class="store-plan-image-wrap"
        />
      </el-col>
      <el-col
        :span="10"
        style="padding-left: 12px;"
      >
        <section class="options-wrap">
          <el-button
            v-blur
            type="primary"
            @click="handleAdd"
          >
            新增
          </el-button>
        </section>

        <el-table
          :data="tableData"
          border
          max-height="62vh"
        >
          <el-table-column
            prop="status"
            width="50"
          >
            <template #default="{row}">
              <span
                v-if="row.status === 1"
                class="icon-select"
              >
                <el-icon><select /></el-icon>
              </span>
              <span
                v-else
                class="icon-close"
              >
                <el-icon><close-bold /></el-icon>
              </span>
            </template>
          </el-table-column>
          <el-table-column
            prop="areaCode"
            label="编号"
            width="70"
          />
          <el-table-column
            prop="color"
            label="区域颜色"
            width="80"
          >
            <template #default="{row}">
              <p
                class="color-block"
                :style="{
                  backgroundColor: row.color
                }"
              />
            </template>
          </el-table-column>
          <el-table-column
            prop="location"
            label="属性"
            min-width="120"
          >
            <template #default="{row}">
              <el-select
                v-model="row.location"
                placeholder="选择属性"
              >
                <el-option
                  v-for="item in propertyList"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </template>
          </el-table-column>
          <el-table-column
            prop="relevanceList"
            label="关联区域"
            min-width="180"
          >
            <template #default="{row}">
              <el-select
                v-model="row.relevanceList"
                placeholder="选择关联区域"
                multiple
                collapse-tags
                style="width: 100%;"
              >
                <el-option
                  v-for="item in linkList"
                  :key="item.value"
                  :disabled="+item.value === +row.areaCode"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </template>
          </el-table-column>
          <el-table-column
            prop="description"
            label="描述"
            min-width="130"
          >
            <template #default="{row}">
              <el-input
                v-model="row.description"
                placeholder="输入描述"
                type="textarea"
                :rows="2"
              />
            </template>
          </el-table-column>
          <el-table-column
            prop="options"
            width="74"
            fixed="right"
          >
            <template #default="{row, $index}">
              <el-button
                v-blur
                type="primary"
                :icon="Edit"
                link
                @click="handleEdit(row)"
              />
              <el-button
                v-blur
                type="primary"
                :icon="Delete"
                link
                @click="handleDelete($index)"
              />
            </template>
          </el-table-column>
        </el-table>
      </el-col>
    </el-row>
    <div class="dialog-footer">
      <el-button
        v-blur
        type="primary"
        @click="handleSubmit"
      >
        确定
      </el-button>
    </div>
    <div class="result-text">
      结果：<pre>{{ requestData }}</pre>
    </div>
  </section>
</template>
<script lang="ts" setup>
import {
  watch, ref, computed, nextTick, onUnmounted,
} from 'vue';

import { CloseBold, Edit, Delete } from '@element-plus/icons-vue';
import { ElMessage } from 'hive-plus';

import aiLabelImage from '@/assets/images/ai-label-image.jpg';
import deleteFillIcon from '@/assets/images/delete-fill.png';
import { loadImage } from '@/utils/file-tools';
import {
  getRandomColor,
  compareColor,
  getPolygonCenter,
} from '@/utils/index';

const getStoreArearequestData: any = {
  code: 0,
  message: 'success',
  data: [
    {
      id: 19,
      storeId: 20,
      areaCode: '1',
      color: '#EFE8B8',
      location: '通道',
      coordinate: [{
        x: 123.8123,
        y: 216.6716,
        className: 'point',
      }, {
        x: 299.4531,
        y: 218.1113,
        className: 'point',
      }, {
        x: 298.0134,
        y: 84.2212,
        className: 'point',
      }, {
        x: 159.8043,
        y: 48.2292,
        className: 'point',
      }, {
        x: 132.4504,
        y: 137.4893,
        className: 'point',
      }],
      relevance: '2',
      center: null,
      description: '通道关联曝光区域',
      createDate: '2023-12-04T03:19:47.000+00:00',
      updateDate: '2023-12-04T03:19:47.000+00:00',
      plan: aiLabelImage,
    },
    {
      id: 20,
      storeId: 20,
      areaCode: '2',
      color: '#C6DC42',
      location: '曝光区',
      coordinate: [{
        x: 38.8713,
        y: -267.0603,
        className: 'point',
      }, {
        x: 299.4531,
        y: -261.3016,
        className: 'point',
      }, {
        x: 253.3834,
        y: -380.7949,
        className: 'point',
      }, {
        x: 35.992,
        y: -363.5188,
        className: 'point',
      }, {
        x: -37.431649061662206,
        y: -320.3284,
        className: 'point',
      }],
      relevance: '1',
      center: null,
      description: '曝光区域关联通道',
      createDate: '2023-12-04T03:19:47.000+00:00',
      updateDate: '2023-12-04T03:19:47.000+00:00',
      plan: aiLabelImage,
    }
  ],
};

const editParams = ref<TypeObject>({});
const propertyList = ref([
  {
    value: '通道',
    label: '通道',
  },
  {
    value: '曝光区',
    label: '曝光区',
  },
  {
    value: '进出口',
    label: '进出口',
  }
]);

const tableData = ref<TypeObject[]>([]);

const requestData = ref();
const linkList = computed(() => tableData.value.map((item) => ({
  value: `${item.areaCode}`,
  label: item.areaCode,
})));
const colorList = computed(() => tableData.value.map((item) => (item.color)));
// 随机获取区域颜色
const getColor = ():string => {
  const color = getRandomColor(true);
  if (colorList.value.some((item) => compareColor(item, color))) {
    return getColor();
  }
  return color;
};

const handleAdd = () => {
  const length = tableData.value.length;
  tableData.value.push({
    storeId: editParams.value.id,
    areaCode: length === 0 ? length + 1 : tableData.value[length - 1].areaCode * 1 + 1,
    status: 0,
    color: getColor(),
    location: '',
    relevanceList: [],
    relevance: '',
    description: '',
    coordinate: '',
    center: '',
  });
};

const loading = ref(false);
const imageInfo = ref();
const gMap = ref();
// 当前编辑的属性信息
const currentRow = ref();
const gFeatureLayer = ref();
const gTextLayer = ref();
const gMarkerLayer = ref();

/**
   * @description: 添加feature
   */
const handleDrawFeatureLayer = (data: TypeObject) => {
  const featureLayerId = `featurePolygon-${data.areaCode}`;
  const cFeature = new (window as any).AILabel.Feature.Polygon(
    featureLayerId,
    data.points,
    {
      name: data.id,
    },
    data.polygonStyle
  );
  gFeatureLayer.value.addFeature(cFeature);
};

/**
   * @description: 添加序号标签
   */
const handleDrawTextLayer = (data: TypeObject) => {
  // 如果已存在序号标签，先移除再添加
  const textLayerId = `featureText-${data.areaCode}`;
  if (gTextLayer.value.getTextById(textLayerId)) {
    gTextLayer.value.removeTextById(textLayerId);
  }

  const gTextStyle = new (window as any).AILabel.Style({
    fontColor: '#FF0000',
    fontSize: 14,
    strokeColor: '#0000FF',
  });
  const bounds = (window as any).AILabel.Util.getBounds(data.points);
  const polygonCenterPoint = getPolygonCenter(bounds); // 获取图形的中心点
  const labelText = new (window as any).AILabel.Text(textLayerId, {
    pos: {
      x: polygonCenterPoint.x,
      y: polygonCenterPoint.y,
    },
    offset: {
      x: 0,
      y: 0,
    },
    text: data.areaCode,
  }, gTextStyle);
  gTextLayer.value.addText(labelText);
};

/**
   * @description: 绘制删除按钮
   */
const handleDrawDeleteMarker = (data: TypeObject) => {
  const featureLayerId = `featurePolygon-${data.areaCode}`;
  const textLayerId = `featureText-${data.areaCode}`;
  const deleteMarkerId = `featureMarker-${data.areaCode}`;
  // 如果已存在删除按钮，先移除再添加
  if (gMarkerLayer.value.getMarkerById(deleteMarkerId)) {
    gMarkerLayer.value.removeMarkerById(deleteMarkerId);
  }
  const bounds = (window as any).AILabel.Util.getBounds(data.points);
  const leftTopPoint = bounds[0]; // 边界坐上角坐标
  const deleteMarker = new (window as any).AILabel.Marker(deleteMarkerId, {
    src: deleteFillIcon,
    x: leftTopPoint.x,
    y: leftTopPoint.y,
    offset: {
      x: 0,
      y: 0,
    },
    featureId: featureLayerId,
  });
  gMarkerLayer.value.addMarker(deleteMarker);

  // 添加删除事件
  deleteMarker.regEvent('click', () => {
    gFeatureLayer.value.removeFeatureById(featureLayerId);
    gTextLayer.value.removeTextById(textLayerId);
    gMarkerLayer.value.removeMarkerById(deleteMarkerId);

    const rowIndex = featureLayerId.split('-')[1];
    const findIndex = tableData.value.findIndex((item:TypeObject) => +item.areaCode === +rowIndex);
    // 重置表格指定行的数据
    tableData.value[findIndex].center = null;
    tableData.value[findIndex].points = null;
    tableData.value[findIndex].status = 0;
  });
};

/**
   * @description: 根据点信息绘制图纸内容
   * @param {*} data 要绘制的区域信息
   * @return {*}
   */
const handleDrawMask = (data: TypeObject) => {
  const findFea = gFeatureLayer.value.getFeatureById(`featurePolygon-${data.areaCode}`);
  if (findFea) {
    ElMessage.error('已存在相似标记，请移除后再绘制！');
    return;
  }

  // 绘制featureLayer
  handleDrawFeatureLayer(data);

  // 绘制textLayer
  handleDrawTextLayer(data);

  // 绘制删除按钮
  handleDrawDeleteMarker(data);

  // 设置区域状态，控制显示是否有在平面图绘制区域
  data.status = 1;
  // 获取并设置中心点坐标信息
  const bounds = (window as any).AILabel.Util.getBounds(data.points);
  data.center = getPolygonCenter(bounds);

  // 设置为预览模式
  gMap.value.setMode('PAN');
  gMap.value.setCursor('pointer');
};

// 给图添加事件
const handleAddEvent = () => {
  gMap.value.events.on('geometryDrawDone', (type:any, points:any) => {
    console.log('geometryDrawDone', type, points);

    currentRow.value.points = points;
    handleDrawMask(currentRow.value); // 绘图
  });

  gMap.value.events.on('geometryEditDone', (type:any, activeFeature:any, points:any) => {
    console.log('geometryEditDone', type, activeFeature, points);

    currentRow.value.points = points;
    // 编辑成功之后设置中心点坐标信息
    currentRow.value.center = getPolygonCenter(points);
    // 更新当前激活的feature的属性
    activeFeature.update({ points });
    // 更新编号标签
    handleDrawTextLayer(currentRow.value);
    // 更新删除按钮
    handleDrawDeleteMarker(currentRow.value);
  });
};
const handleInitGMap = async() => {
  if (!editParams.value.plan) {
    ElMessage.error('请先上传平面图！');
    return;
  }

  try {
    loading.value = true;
    const imageMsg:any = await loadImage(editParams.value.plan).catch(() => {
      ElMessage.error('加载图片失败！');
    }).finally(() => {
      loading.value = false;
    });
    imageInfo.value = {
      width: 1674,
      height: 1518,
      image: imageMsg,
    };

    gMap.value = new (window as any).AILabel.Map('storePlanImageId', {
      center: {
        x: imageInfo.value.width / 2,
        y: imageInfo.value.height / 2,
      }, // 为了让图片居中
      zoom: imageInfo.value.height > imageInfo.value.width ? imageInfo.value.height : imageInfo.value.width,
      mode: 'PAN', // 绘制线段
      refreshDelayWhenZooming: true, // 缩放时是否允许刷新延时，性能更优
      zoomWhenDrawing: true,
      panWhenDrawing: true,
      zoomWheelRatio: 5, // 控制滑轮缩放缩率[0, 10), 值越小，则缩放越快，反之越慢
      withHotKeys: false, // 关闭快捷键
    });
    // 设置为预览模式
    gMap.value.setMode('PAN');
    gMap.value.setCursor('pointer');

    // 添加事件
    handleAddEvent();

    const gFirstImageLayer = new (window as any).AILabel.Layer.Image(
      'first-layer-image', // id
      editParams.value.plan,
      {
        w: imageInfo.value.width,

        h: imageInfo.value.height,

        crossOrigin: false, // 如果跨域图片，需要设置为true
        position: { // 左上角相对中心点偏移量
          x: 0,
          y: 0,
        },
      },
      {
        zIndex: 5,
      }
    );
      // 添加到gMap对象
    gMap.value.addLayer(gFirstImageLayer);

    // 添加矢量图层
    const gFirstFeatureLayer = new (window as any).AILabel.Layer.Feature(
      'first-layer-feature',
      { zIndex: 10 }
    );
    gFeatureLayer.value = gFirstFeatureLayer;
    gMap.value.addLayer(gFirstFeatureLayer);
    // 添加标注
    const gFirstTextLayer = new (window as any).AILabel.Layer.Text(
      'first-layer-text',
      { zIndex: 15, opacity: 1 }
    );
    gTextLayer.value = gFirstTextLayer;
    gMap.value.addLayer(gFirstTextLayer);
    // 添加Marker
    const gFirstMarkerLayer = new (window as any).AILabel.Layer.Marker(
      'first-layer-marker',
      { zIndex: 20, opacity: 1 }
    );
    gMarkerLayer.value = gFirstMarkerLayer;
    gMap.value.addLayer(gFirstMarkerLayer);

    // 图纸已编辑内容的回显
    if (tableData.value && tableData.value.length) {
      tableData.value.forEach((row) => {
        const polygonStyle = {
          strokeColor: row.color,
          fillColor: row.color,
          opacity: 0.5,
          lineWeight: 2,
        };
        row.polygonStyle = polygonStyle;
        if (row.points && row.points.length) {
          handleDrawMask(row);
        }
      });
    }

    window.onresize = () => {
      gMap?.value?.resize();
    };
  } catch (error) {
    console.error('AILabel错误：', error);
  }
};

/**
   * @description: 设置图纸中的feature不可编辑
   */
const handleSetFeaturesDeActive = () => {
  const allFeatures = gFeatureLayer.value.getAllFeatures();
  allFeatures.forEach((feature:any) => {
    feature.deActive();
  });
};

const handleEdit = (row: TypeObject) => {
  if (row.points && row.points.length > 0) {
    // 清空feature的可编辑状态
    handleSetFeaturesDeActive();

    // 已存在的feature只能编辑
    const currentFeature = gFeatureLayer.value.getFeatureById(`featurePolygon-${row.areaCode}`);
    // 设置为可编辑状态
    currentFeature?.active();
  }

  const polygonStyle = {
    strokeColor: row.color,
    fillColor: row.color,
    opacity: 0.5,
    lineWeight: 2,
  };
  currentRow.value = row;
  currentRow.value.polygonStyle = polygonStyle;
  gMap.value.setMode('drawPolygon', polygonStyle);
};

const handleDelete = (index: number) => {
  const findInfo = tableData.value[index];
  // 删除标记物
  gFeatureLayer.value.removeFeatureById(`featurePolygon-${findInfo.areaCode}`);
  gTextLayer.value.removeTextById(`featureText-${findInfo.areaCode}`);
  gMarkerLayer.value.removeMarkerById(`featureMarker-${findInfo.areaCode}`);
  // 重置currentRow
  currentRow.value = null;
  // 设置为预览模式
  gMap.value.setMode('PAN');
  gMap.value.setCursor('pointer');

  tableData.value.splice(index, 1);
};
const editParamsData = {
  id: 20,
  storeName: '龙湖天街Nike店',
  brandId: 1,
  brandName: '',
  gatewaySn: 'SN12313123dddd',
  cameraCount: 0,
  person: 0,
  area: '',
  plan: aiLabelImage,
  effective: 1,
  createDate: '2023-12-04T03:18:51.000+00:00',
  updateDate: null,
  areaCount: 2,
  areaDescription: [
    '通道关联曝光区域',
    '曝光区域关联通道'
  ],
  planWidth: 0,
  planHeight: 0,
};
watch(
  () => false,
  () => {
    nextTick(() => {
      if (Object.keys(editParamsData).length > 0) {
        editParams.value = { ...editParamsData };
      }
      const resultData = getStoreArearequestData.data || [];
      tableData.value = [...resultData];
      tableData.value.forEach((item) => {
        item.relevanceList = item.relevance ? item.relevance.split(',') : [];
        item.points = item.coordinate ? item.coordinate : [];
        item.center = item.center ? item.center : {};
        item.status = item.points && item.points.length > 0 ? 1 : 0;
      });
      // 图纸编辑框初始化
      handleInitGMap();
    });
  },
  {
    immediate: true,
  }
);

const handleSubmit = () => {
  const requestParams = tableData.value.map((item) => ({
    ...item,
    coordinate: item.points ? JSON.stringify(item.points) : '',
    relevance: item.relevanceList && item.relevanceList.length ? item.relevanceList.join(',') : '',
    center: item.center ? JSON.stringify(item.center) : '',
  }));
  requestData.value = [];
  requestData.value = requestParams;
};

onUnmounted(() => {
  gMap?.value?.destroy();
});
</script>
<style scoped lang="scss">
.dialog-body {
  width: 100%;
  height: 90vh;
  overflow-y: auto;

  .store-plan-image-wrap {
    position: relative;
    height: 69vh;
    border: 1px dashed var(--#{$namespace}-border-color-base);
  }

  .options-wrap {
    padding: 10px 0;
    text-align: right;
  }

  .icon-select {
    color: #7dd75a;
  }

  .icon-close {
    color: #dc5564;
  }

  .color-block {
    height: 20px;
  }

  .dialog-footer {
    text-align: right;
  }

  .result-text {
    height: 160px;
    overflow: auto;
    background: #fff;
  }
}
</style>
